#pragma once
#include "GUIState.h"

// Diagnostic Form
//
// This form is used to show system diagnostic information.
//
// This includes:
//    Out Buffer Putter Position
//    Out Buffer Getter Position
//    Out Buffer Capacity
//
//    In Buffer Putter Position
//    In Buffer Getter Position
//    In Buffer Capacity
//
// This form is periodically updated via the GUIState object's timer tick.

namespace CC3501_Main_GUI {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;

	/// <summary>
	/// Summary for Diagnostic
	/// </summary>
	public ref class Diagnostic : public System::Windows::Forms::Form
	{
	public:
		// Constructor
		//
		// The Diagnostic form requires a reference to the shared GUIState class.
		Diagnostic(GUIState^ existingState)
		{
			InitializeComponent();
			extraInitializeComponent();
			this->state = existingState;
			this->evHandler = gcnew ElapsedEventHandler(this, &Diagnostic::handleTimerTick);
			this->state->getTimer()->addTickHandler(evHandler);
			

			updateProgressBar();
			updateProgressBarValues();
			
		}
		delegate void HandleTimerTickDelegate(void);

		// Handle the timer tick
		void Tick(void)
		{
			updateProgressBar();
			updateProgressBarValues();			
		}

	protected:
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		~Diagnostic()
		{
			if (components)
			{
				delete components;
			}
		}

	private:
		// Our save state
		GUIState^ state;
		ElapsedEventHandler^ evHandler;

	private: System::Windows::Forms::ProgressBar^  inBufferSpaceProgressBar;
	private: System::Windows::Forms::ProgressBar^  outBufferSpaceProgressBar;
	private: System::Windows::Forms::Label^  inBufferCapacityLabel;
	private: System::Windows::Forms::Label^  outBufferCapacityLabel;
	private: System::Windows::Forms::ProgressBar^  inBufferPutterPositionProgressBar;
	private: System::Windows::Forms::ProgressBar^  inBufferGetterPositionProgressBar;
	private: System::Windows::Forms::Label^  inBufferPutterHeadingLabel;
	private: System::Windows::Forms::Label^  inBufferGetterHeadingLabel;
	private: System::Windows::Forms::Label^  outBufferGetterHeadingLabel;
	private: System::Windows::Forms::Label^  outBufferPutterHeadingLabel;
	private: System::Windows::Forms::ProgressBar^  outBufferGetterPositionProgressBar;
	private: System::Windows::Forms::ProgressBar^  outBufferPutterPositionProgressBar;
	private: System::Windows::Forms::Panel^  panel1;
	private: System::Windows::Forms::Panel^  panel2;
	private: System::Windows::Forms::Label^  inBufferSpaceLabel;
	private: System::Windows::Forms::Label^  outBufferGetterPositionLabel;
	private: System::Windows::Forms::Label^  outBufferPutterPositionLabel;
	private: System::Windows::Forms::Label^  outBufferSpaceLabel;
	private: System::Windows::Forms::Label^  inBufferGetterPositionLabel;
	private: System::Windows::Forms::Label^  inBufferPutterPositionLabel;
	private: System::Windows::Forms::Label^  currentValuesHeadingLabel;
	private: System::Windows::Forms::Label^  currentBufferCapacitiesHeadingLabel;
			 /// </summary>
			 System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
			 /// <summary>
			 /// Required method for Designer support - do not modify
			 /// the contents of this method with the code editor.
			 /// </summary>
			 void InitializeComponent(void)
			 {
				 this->inBufferSpaceProgressBar = (gcnew System::Windows::Forms::ProgressBar());
				 this->outBufferSpaceProgressBar = (gcnew System::Windows::Forms::ProgressBar());
				 this->inBufferCapacityLabel = (gcnew System::Windows::Forms::Label());
				 this->outBufferCapacityLabel = (gcnew System::Windows::Forms::Label());
				 this->inBufferPutterPositionProgressBar = (gcnew System::Windows::Forms::ProgressBar());
				 this->inBufferGetterPositionProgressBar = (gcnew System::Windows::Forms::ProgressBar());
				 this->inBufferPutterHeadingLabel = (gcnew System::Windows::Forms::Label());
				 this->inBufferGetterHeadingLabel = (gcnew System::Windows::Forms::Label());
				 this->outBufferGetterHeadingLabel = (gcnew System::Windows::Forms::Label());
				 this->outBufferPutterHeadingLabel = (gcnew System::Windows::Forms::Label());
				 this->outBufferGetterPositionProgressBar = (gcnew System::Windows::Forms::ProgressBar());
				 this->outBufferPutterPositionProgressBar = (gcnew System::Windows::Forms::ProgressBar());
				 this->panel1 = (gcnew System::Windows::Forms::Panel());
				 this->currentBufferCapacitiesHeadingLabel = (gcnew System::Windows::Forms::Label());
				 this->panel2 = (gcnew System::Windows::Forms::Panel());
				 this->outBufferGetterPositionLabel = (gcnew System::Windows::Forms::Label());
				 this->outBufferPutterPositionLabel = (gcnew System::Windows::Forms::Label());
				 this->outBufferSpaceLabel = (gcnew System::Windows::Forms::Label());
				 this->inBufferGetterPositionLabel = (gcnew System::Windows::Forms::Label());
				 this->inBufferPutterPositionLabel = (gcnew System::Windows::Forms::Label());
				 this->currentValuesHeadingLabel = (gcnew System::Windows::Forms::Label());
				 this->inBufferSpaceLabel = (gcnew System::Windows::Forms::Label());
				 this->panel1->SuspendLayout();
				 this->panel2->SuspendLayout();
				 this->SuspendLayout();
				 // 
				 // inBufferSpaceProgressBar
				 // 
				 this->inBufferSpaceProgressBar->Location = System::Drawing::Point(6, 49);
				 this->inBufferSpaceProgressBar->Name = L"inBufferSpaceProgressBar";
				 this->inBufferSpaceProgressBar->Size = System::Drawing::Size(431, 54);
				 this->inBufferSpaceProgressBar->TabIndex = 0;
				 // 
				 // outBufferSpaceProgressBar
				 // 
				 this->outBufferSpaceProgressBar->Location = System::Drawing::Point(6, 235);
				 this->outBufferSpaceProgressBar->Name = L"outBufferSpaceProgressBar";
				 this->outBufferSpaceProgressBar->Size = System::Drawing::Size(431, 54);
				 this->outBufferSpaceProgressBar->TabIndex = 1;
				 // 
				 // inBufferCapacityLabel
				 // 
				 this->inBufferCapacityLabel->AutoSize = true;
				 this->inBufferCapacityLabel->Location = System::Drawing::Point(6, 33);
				 this->inBufferCapacityLabel->Name = L"inBufferCapacityLabel";
				 this->inBufferCapacityLabel->Size = System::Drawing::Size(128, 13);
				 this->inBufferCapacityLabel->TabIndex = 2;
				 this->inBufferCapacityLabel->Text = L"In Buffer Current Capacity";
				 // 
				 // outBufferCapacityLabel
				 // 
				 this->outBufferCapacityLabel->AutoSize = true;
				 this->outBufferCapacityLabel->Location = System::Drawing::Point(6, 219);
				 this->outBufferCapacityLabel->Name = L"outBufferCapacityLabel";
				 this->outBufferCapacityLabel->Size = System::Drawing::Size(136, 13);
				 this->outBufferCapacityLabel->TabIndex = 3;
				 this->outBufferCapacityLabel->Text = L"Out Buffer Current Capacity";
				 // 
				 // inBufferPutterPositionProgressBar
				 // 
				 this->inBufferPutterPositionProgressBar->BackColor = System::Drawing::SystemColors::AppWorkspace;
				 this->inBufferPutterPositionProgressBar->ForeColor = System::Drawing::SystemColors::GradientActiveCaption;
				 this->inBufferPutterPositionProgressBar->Location = System::Drawing::Point(6, 122);
				 this->inBufferPutterPositionProgressBar->Name = L"inBufferPutterPositionProgressBar";
				 this->inBufferPutterPositionProgressBar->Size = System::Drawing::Size(431, 17);
				 this->inBufferPutterPositionProgressBar->TabIndex = 5;
				 // 
				 // inBufferGetterPositionProgressBar
				 // 
				 this->inBufferGetterPositionProgressBar->BackColor = System::Drawing::SystemColors::ActiveCaption;
				 this->inBufferGetterPositionProgressBar->ForeColor = System::Drawing::SystemColors::ControlText;
				 this->inBufferGetterPositionProgressBar->Location = System::Drawing::Point(6, 157);
				 this->inBufferGetterPositionProgressBar->Name = L"inBufferGetterPositionProgressBar";
				 this->inBufferGetterPositionProgressBar->Size = System::Drawing::Size(431, 17);
				 this->inBufferGetterPositionProgressBar->TabIndex = 6;
				 // 
				 // inBufferPutterHeadingLabel
				 // 
				 this->inBufferPutterHeadingLabel->AutoSize = true;
				 this->inBufferPutterHeadingLabel->Location = System::Drawing::Point(6, 106);
				 this->inBufferPutterHeadingLabel->Name = L"inBufferPutterHeadingLabel";
				 this->inBufferPutterHeadingLabel->Size = System::Drawing::Size(122, 13);
				 this->inBufferPutterHeadingLabel->TabIndex = 7;
				 this->inBufferPutterHeadingLabel->Text = L"In Buffer Putter Location";
				 // 
				 // inBufferGetterHeadingLabel
				 // 
				 this->inBufferGetterHeadingLabel->AutoSize = true;
				 this->inBufferGetterHeadingLabel->Location = System::Drawing::Point(6, 142);
				 this->inBufferGetterHeadingLabel->Name = L"inBufferGetterHeadingLabel";
				 this->inBufferGetterHeadingLabel->Size = System::Drawing::Size(123, 13);
				 this->inBufferGetterHeadingLabel->TabIndex = 8;
				 this->inBufferGetterHeadingLabel->Text = L"In Buffer Getter Location";
				 // 
				 // outBufferGetterHeadingLabel
				 // 
				 this->outBufferGetterHeadingLabel->AutoSize = true;
				 this->outBufferGetterHeadingLabel->Location = System::Drawing::Point(6, 332);
				 this->outBufferGetterHeadingLabel->Name = L"outBufferGetterHeadingLabel";
				 this->outBufferGetterHeadingLabel->Size = System::Drawing::Size(131, 13);
				 this->outBufferGetterHeadingLabel->TabIndex = 12;
				 this->outBufferGetterHeadingLabel->Text = L"Out Buffer Getter Location";
				 // 
				 // outBufferPutterHeadingLabel
				 // 
				 this->outBufferPutterHeadingLabel->AutoSize = true;
				 this->outBufferPutterHeadingLabel->Location = System::Drawing::Point(6, 296);
				 this->outBufferPutterHeadingLabel->Name = L"outBufferPutterHeadingLabel";
				 this->outBufferPutterHeadingLabel->Size = System::Drawing::Size(130, 13);
				 this->outBufferPutterHeadingLabel->TabIndex = 11;
				 this->outBufferPutterHeadingLabel->Text = L"Out Buffer Putter Location";
				 // 
				 // outBufferGetterPositionProgressBar
				 // 
				 this->outBufferGetterPositionProgressBar->BackColor = System::Drawing::SystemColors::ActiveCaption;
				 this->outBufferGetterPositionProgressBar->ForeColor = System::Drawing::SystemColors::ControlText;
				 this->outBufferGetterPositionProgressBar->Location = System::Drawing::Point(6, 347);
				 this->outBufferGetterPositionProgressBar->Name = L"outBufferGetterPositionProgressBar";
				 this->outBufferGetterPositionProgressBar->Size = System::Drawing::Size(431, 17);
				 this->outBufferGetterPositionProgressBar->TabIndex = 10;
				 // 
				 // outBufferPutterPositionProgressBar
				 // 
				 this->outBufferPutterPositionProgressBar->BackColor = System::Drawing::SystemColors::AppWorkspace;
				 this->outBufferPutterPositionProgressBar->ForeColor = System::Drawing::SystemColors::GradientActiveCaption;
				 this->outBufferPutterPositionProgressBar->Location = System::Drawing::Point(6, 312);
				 this->outBufferPutterPositionProgressBar->Name = L"outBufferPutterPositionProgressBar";
				 this->outBufferPutterPositionProgressBar->Size = System::Drawing::Size(431, 17);
				 this->outBufferPutterPositionProgressBar->TabIndex = 9;
				 // 
				 // panel1
				 // 
				 this->panel1->BorderStyle = System::Windows::Forms::BorderStyle::Fixed3D;
				 this->panel1->Controls->Add(this->currentBufferCapacitiesHeadingLabel);
				 this->panel1->Controls->Add(this->outBufferGetterHeadingLabel);
				 this->panel1->Controls->Add(this->outBufferPutterHeadingLabel);
				 this->panel1->Controls->Add(this->outBufferGetterPositionProgressBar);
				 this->panel1->Controls->Add(this->outBufferPutterPositionProgressBar);
				 this->panel1->Controls->Add(this->inBufferGetterHeadingLabel);
				 this->panel1->Controls->Add(this->inBufferPutterHeadingLabel);
				 this->panel1->Controls->Add(this->inBufferGetterPositionProgressBar);
				 this->panel1->Controls->Add(this->inBufferPutterPositionProgressBar);
				 this->panel1->Controls->Add(this->outBufferCapacityLabel);
				 this->panel1->Controls->Add(this->inBufferCapacityLabel);
				 this->panel1->Controls->Add(this->outBufferSpaceProgressBar);
				 this->panel1->Controls->Add(this->inBufferSpaceProgressBar);
				 this->panel1->Location = System::Drawing::Point(10, 22);
				 this->panel1->Name = L"panel1";
				 this->panel1->Size = System::Drawing::Size(453, 370);
				 this->panel1->TabIndex = 13;
				 // 
				 // currentBufferCapacitiesHeadingLabel
				 // 
				 this->currentBufferCapacitiesHeadingLabel->AutoSize = true;
				 this->currentBufferCapacitiesHeadingLabel->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 10));
				 this->currentBufferCapacitiesHeadingLabel->Location = System::Drawing::Point(6, 1);
				 this->currentBufferCapacitiesHeadingLabel->Name = L"currentBufferCapacitiesHeadingLabel";
				 this->currentBufferCapacitiesHeadingLabel->Size = System::Drawing::Size(166, 17);
				 this->currentBufferCapacitiesHeadingLabel->TabIndex = 17;
				 this->currentBufferCapacitiesHeadingLabel->Text = L"Current Buffer Capacities";
				 // 
				 // panel2
				 // 
				 this->panel2->BorderStyle = System::Windows::Forms::BorderStyle::Fixed3D;
				 this->panel2->Controls->Add(this->outBufferGetterPositionLabel);
				 this->panel2->Controls->Add(this->outBufferPutterPositionLabel);
				 this->panel2->Controls->Add(this->outBufferSpaceLabel);
				 this->panel2->Controls->Add(this->inBufferGetterPositionLabel);
				 this->panel2->Controls->Add(this->inBufferPutterPositionLabel);
				 this->panel2->Controls->Add(this->currentValuesHeadingLabel);
				 this->panel2->Controls->Add(this->inBufferSpaceLabel);
				 this->panel2->Location = System::Drawing::Point(472, 23);
				 this->panel2->Name = L"panel2";
				 this->panel2->Size = System::Drawing::Size(107, 368);
				 this->panel2->TabIndex = 14;
				 // 
				 // outBufferGetterPositionLabel
				 // 
				 this->outBufferGetterPositionLabel->AutoSize = true;
				 this->outBufferGetterPositionLabel->Location = System::Drawing::Point(13, 348);
				 this->outBufferGetterPositionLabel->Name = L"outBufferGetterPositionLabel";
				 this->outBufferGetterPositionLabel->Size = System::Drawing::Size(0, 13);
				 this->outBufferGetterPositionLabel->TabIndex = 21;
				 // 
				 // outBufferPutterPositionLabel
				 // 
				 this->outBufferPutterPositionLabel->AutoSize = true;
				 this->outBufferPutterPositionLabel->Location = System::Drawing::Point(13, 313);
				 this->outBufferPutterPositionLabel->Name = L"outBufferPutterPositionLabel";
				 this->outBufferPutterPositionLabel->Size = System::Drawing::Size(0, 13);
				 this->outBufferPutterPositionLabel->TabIndex = 20;
				 // 
				 // outBufferSpaceLabel
				 // 
				 this->outBufferSpaceLabel->AutoSize = true;
				 this->outBufferSpaceLabel->Location = System::Drawing::Point(13, 251);
				 this->outBufferSpaceLabel->Name = L"outBufferSpaceLabel";
				 this->outBufferSpaceLabel->Size = System::Drawing::Size(0, 13);
				 this->outBufferSpaceLabel->TabIndex = 19;
				 // 
				 // inBufferGetterPositionLabel
				 // 
				 this->inBufferGetterPositionLabel->AutoSize = true;
				 this->inBufferGetterPositionLabel->Location = System::Drawing::Point(13, 162);
				 this->inBufferGetterPositionLabel->Name = L"inBufferGetterPositionLabel";
				 this->inBufferGetterPositionLabel->Size = System::Drawing::Size(0, 13);
				 this->inBufferGetterPositionLabel->TabIndex = 18;
				 // 
				 // inBufferPutterPositionLabel
				 // 
				 this->inBufferPutterPositionLabel->AutoSize = true;
				 this->inBufferPutterPositionLabel->Location = System::Drawing::Point(13, 123);
				 this->inBufferPutterPositionLabel->Name = L"inBufferPutterPositionLabel";
				 this->inBufferPutterPositionLabel->Size = System::Drawing::Size(0, 13);
				 this->inBufferPutterPositionLabel->TabIndex = 17;
				 // 
				 // currentValuesHeadingLabel
				 // 
				 this->currentValuesHeadingLabel->AutoSize = true;
				 this->currentValuesHeadingLabel->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 10));
				 this->currentValuesHeadingLabel->Location = System::Drawing::Point(-2, 0);
				 this->currentValuesHeadingLabel->Name = L"currentValuesHeadingLabel";
				 this->currentValuesHeadingLabel->Size = System::Drawing::Size(102, 17);
				 this->currentValuesHeadingLabel->TabIndex = 16;
				 this->currentValuesHeadingLabel->Text = L"Current Values";
				 // 
				 // inBufferSpaceLabel
				 // 
				 this->inBufferSpaceLabel->AutoSize = true;
				 this->inBufferSpaceLabel->Location = System::Drawing::Point(13, 66);
				 this->inBufferSpaceLabel->Name = L"inBufferSpaceLabel";
				 this->inBufferSpaceLabel->Size = System::Drawing::Size(0, 13);
				 this->inBufferSpaceLabel->TabIndex = 15;
				 // 
				 // Diagnostic
				 // 
				 this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
				 this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
				 this->ClientSize = System::Drawing::Size(589, 403);
				 this->Controls->Add(this->panel2);
				 this->Controls->Add(this->panel1);
				 this->Name = L"Diagnostic";
				 this->Text = L"Diagnostic";
				 this->FormClosing += gcnew System::Windows::Forms::FormClosingEventHandler(this, &Diagnostic::Diagnostic_FormClosing);
				 this->panel1->ResumeLayout(false);
				 this->panel1->PerformLayout();
				 this->panel2->ResumeLayout(false);
				 this->panel2->PerformLayout();
				 this->ResumeLayout(false);

			 }
			 void extraInitializeComponent(void)
			 {
				 this->inBufferSpaceProgressBar->Minimum = 0;
				 this->inBufferSpaceProgressBar->Maximum = GUIState::inBufferSize;
				 this->outBufferSpaceProgressBar->Minimum = 0;
				 this->outBufferSpaceProgressBar->Maximum = GUIState::outBufferSize;

				 //Getter/putter for in buffer
				 this->inBufferPutterPositionProgressBar->Minimum = 0;
				 this->inBufferPutterPositionProgressBar->Maximum = GUIState::inBufferSize;
				 this->inBufferGetterPositionProgressBar->Minimum = 0;
				 this->inBufferGetterPositionProgressBar->Maximum = GUIState::inBufferSize;

				 //Getter/putter for out buffer
				 this->outBufferGetterPositionProgressBar->Minimum = 0;
				 this->outBufferGetterPositionProgressBar->Maximum = GUIState::outBufferSize;
				 this->outBufferPutterPositionProgressBar->Minimum = 0;
				 this->outBufferPutterPositionProgressBar->Maximum = GUIState::outBufferSize;

				 //Actual Value labels
				 this->inBufferSpaceLabel->Text = "0";
				 this->inBufferPutterPositionLabel->Text = "0";
				 this->inBufferGetterPositionLabel->Text = "0";
				 this->outBufferSpaceLabel->Text = "0";
				 this->outBufferPutterPositionLabel->Text = "0";
				 this->outBufferGetterPositionLabel->Text = "0";
			 }
	public: void updateProgressBar(void)
			{
				int inBufSpace = this->state->getInBufferSpace();
				this->inBufferSpaceProgressBar->Value = inBufSpace;

				int outBufSpace = this->state->getOutBufferSpace();
				this->outBufferSpaceProgressBar->Value = outBufSpace;

				this->inBufferPutterPositionProgressBar->Value = this->state->getInBufferPutterPosition();
				this->inBufferGetterPositionProgressBar->Value = this->state->getInBufferGetterPosition();
				this->outBufferGetterPositionProgressBar->Value = this->state->getOutBufferGetterPosition();
				this->outBufferPutterPositionProgressBar->Value = this->state->getOutBufferPutterPosition();
			}

	public: void updateProgressBarValues(void)
			{
				this->inBufferSpaceLabel->Text = System::Convert::ToString(this->state->getInBufferSpace());
				this->inBufferPutterPositionLabel->Text = System::Convert::ToString(this->state->getInBufferPutterPosition());
				this->inBufferGetterPositionLabel->Text = System::Convert::ToString(this->state->getInBufferGetterPosition());

				this->outBufferSpaceLabel->Text = System::Convert::ToString(this->state->getOutBufferSpace());
				this->outBufferPutterPositionLabel->Text = System::Convert::ToString(this->state->getOutBufferPutterPosition());
				this->outBufferGetterPositionLabel->Text = System::Convert::ToString(this->state->getOutBufferGetterPosition());				
			}
	private: System::Void handleTimerTick(System::Object^  sender, ElapsedEventArgs^  e) {
				 //Debugger::Log(0, nullptr, ".\n");
				 // run the UpDateTimer function on this...
				 // Note: we say this->Invoke, as we need the GUI thread to execute the timer update.
				 // The Invoke ensures that the delegate function is run by the GUI thread.
				 // If you don't do this, it will exception..
				 // so..
				 // it is running UpDateTimer (via the UpdateTimerNew delegate) on "this" (which is the form)
				 // within the thread of the GUI... and breathe..
				 this->Invoke(gcnew HandleTimerTickDelegate(this, &Diagnostic::Tick));

				 // this->Invoke(this->UpdateTimerNew);
			 };
#pragma endregion

	private: System::Void Diagnostic_FormClosing(System::Object^  sender, System::Windows::Forms::FormClosingEventArgs^  e) {
				 this->state->getTimer()->removeTickHandler(this->evHandler);				
			 }
	};

}
